# -*- coding: utf-8 -*-
import time, subprocess, os
from pydub import AudioSegment
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage

""" #音频详细信息
from pydub.utils import which
AudioSegment.converter = which("ffmpeg") """

record_path = "/storage/emulated/legacy/Record/%s.aac"
camera_path = "/storage/emulated/legacy/Camera/%s.jpg"
#camera_base = "/storage/emulated/legacy/Camera/base.jpg" #由于没写运动监测，不需要了
record_cmd_start = "termux-microphone-record -e aac -f "
record_cmd_exit = "termux-microphone-record -q"
camera_cmd = "termux-camera-photo -c 1 " #前置摄像头600kb，后置1.2mb
del_cmd = "rm -rf "
timestamp = 0.01
temp_path = ''
cycle_time = 5 #录音模式5秒一次循环判断
alarm_db = 55 #经测试，55分贝代表开门了，无人环境为40-45分贝左右

#设置服务器所需信息
#163邮箱服务器地址
mail_host = ''  
#163用户名
mail_user = ''  
#密码(部分邮箱为授权码) 网易云邮箱授权密码
mail_pass = ''   
#邮件发送方邮箱地址
sender = ''  
#邮件接受方邮箱地址，注意需要[]包裹，这意味着你可以写多个邮件地址群发
receivers = ['']

def 命令(work_cmd):
    try:
        #stdout=subprocess.PIPE 将命令的结果输出转到自建管道，不显示出来
        p = subprocess.run(work_cmd, stdout=subprocess.PIPE, timeout=8, shell=True)
        if p.returncode == 0:
            return True
        else:
            print("进程失败", work_cmd)
            return False
    except:
        print("进程 try 失败", work_cmd)
        return False

def 重复命令(work_cmd):
    num = 0
    retcode = False
    while not(retcode) and num < 3:
        retcode = 命令(work_cmd)
        if not(retcode): kill()
        num += 1
    return retcode

def kill():
    try:
        p = subprocess.Popen(['ps', '-A'], stdout=subprocess.PIPE)
        out, err = p.communicate()
        for line in out.splitlines():
            if "com.termux.api" in str(line):
                pid = int(line.split(None, 1)[0])
                os.kill(pid, 9) #9是Kill a process with a signal.
    except:
        pass

def 录音():
    global temp_path
    temp_path = record_path % time.time()
    print("开始录音", end=' ')
    retcode = 重复命令(record_cmd_start + temp_path)
    if not(retcode):
        print("开始录音出现bug")
        邮件("开始录音bug")
    time.sleep(1)
    retcode = 重复命令(record_cmd_exit)
    if not(retcode):
        print("结束录音出现bug")
        邮件("结束录音bug")
        return False
    print("录音结束", end=' ')
    db = False
    num = 0
    while not(db) and num < 3:
        db = 分贝()
        num += 1
    命令(del_cmd + temp_path)
    if db > alarm_db:
        print("分贝", db, "进入拍照模式")
        return True
    elif not(db):
        print('分贝解析bug')
    else:
        print("分贝", db)

def 分贝():
    try:
        print('分贝解析')
        sound = AudioSegment.from_file(temp_path)
        #"/storage/emulated/legacy/Record/1.mp3" 手机监测63db，sound.dBFS监测-38，96+(-38)=58
        db = 96+sound.dBFS #dBFS最大值是0，最小-96，因此96+dBFS能得出实际分贝。
        return db
    except:# Exception as e:
        #print('分贝解析失败', e.args)
        return False

def 拍照():
    global temp_path
    temp_path = camera_path % time.time()
    print("开始拍照", end=' ')
    if 命令(camera_cmd + temp_path):
        print("拍照结束")
        if 大小() != 0:
            if 压缩():
                print("压缩成功")
                return True
        print("图片或压缩问题")
    else:
        kill()
        print("拍照出现bug")
    命令(del_cmd + temp_path)
    return False

def 压缩():
    print("开始压缩", end=' ')
    return 命令("convert -quality 30 "+ temp_path +" " + temp_path)
    """ from PIL import Image
    name = "/storage/emulated/legacy/Camera/base"
    img = Image.open('{}.jpg'.format(name))
    img.save('{}_pil_90.jpg'.format(name), quality=90)
    img.save('{}_pil_75.jpg'.format(name), quality=75)
    img.save('{}_pil_60.jpg'.format(name), quality=60)
    img.save('{}_pil_45.jpg'.format(name), quality=45)
    img.save('{}_pil_30.jpg'.format(name), quality=30)
    img.save('{}_pil_1.jpg'.format(name), quality=1) """

    """ import zipfile
    f = zipfile.ZipFile("/storage/emulated/legacy/asd.zip", 'w', zipfile.ZIP_DEFLATED)
    f.write("/storage/emulated/legacy/1.jpg")
    f.close()
    import gzip
    g = gzip.GzipFile(filename="", mode="wb", compresslevel=9, fileobj=open('sitemap.log.gz', 'wb'))
    g.write(open(r"IMG_20200627_142733.jpg").read())
    g.close() """

def 大小():
    try:
        return os.path.getsize(temp_path) / 1024
    except:
        return 0

def 邮件(bug=""):
    print("开始准备邮件", end=' ')
    #设置email信息
    #添加一个MIMEmultipart类，处理正文及附件
    message = MIMEMultipart()
    if bug == "":
        try:
            #添加照片附件
            with open(temp_path,'rb') as fp:
                picture = MIMEImage(fp.read())
                picture['Content-Type'] = 'application/octet-stream'
                picture['Content-Disposition'] = 'attachment;filename="'+temp_path+'"'
            #将内容附加到邮件主体中
            message.attach(picture)
            bug = "有人来啦！"
        except Exception as e:
            bug = "照片有问题"
            print(bug, e)
            
    #邮件主题
    message['Subject'] = bug
    #发送方信息
    message['From'] = sender
    #接受方信息
    message['To'] = receivers[0]
    #添加正文内容
    part1 = MIMEText("看附件",'html','utf-8')
    message.attach(part1)

    #登录并发送邮件
    try:
        smtpObj = smtplib.SMTP()
        #连接到服务器
        try:
            smtpObj.connect(mail_host,25)
        except:
            print("网络问题：邮件发送失败")
            return
        #登录到服务器
        smtpObj.login(mail_user,mail_pass)
        #发送
        smtpObj.sendmail(sender,receivers,message.as_string())
        #退出
        smtpObj.quit()
        print('发送邮件成功')
    except smtplib.SMTPException as e:
        print('邮件错误',e) #打印错误

def 循环(s):
    global alarm_db
    temp_s = s
    temp_db = alarm_db
    temp_num = 0
    while True: #保证程序持续运行
        if 录音():
            temp_num = 1 #录音模式转入1秒一次判断
            #在紧急阶段转入拍照
            for i in range(1,10):
                if 拍照():
                    if 大小() > 55: #图片压缩后大于55kb才是有内容
                        邮件()
                    else:
                        print('有声无人')
                    命令(del_cmd + temp_path)
                    break
        else:
            if temp_num != 0:
                temp_num += 1
                if temp_num == 2:
                    s = 1
                    alarm_db = 45 #紧急阶段分贝数要求调低，根据个人环境调节，由于如果一片黑不发邮件，所以降低分贝并不会太多邮件影响。
                elif temp_num > 50:
                    s = temp_s
                    temp_num = 0
                    alarm_db = temp_db
            time.sleep(s)

if __name__ == '__main__':
    循环(cycle_time)
    """ from pydub.utils import mediainfo
    print(mediainfo(record_path % "test")) #音频详细信息"""